Reducción de dimensionalidad¶

Las técnicas de reducción de dimensionalidad son métodos utilizados para reducir el número de variables o dimensiones en un conjunto de datos mientras se intenta retener la mayor cantidad posible de información importante. Estas técnicas son especialmente útiles cuando se trabaja con conjuntos de datos de alta dimensionalidad, donde el número de características es grande y puede haber redundancia o ruido en los datos. La reducción de dimensionalidad ayuda a simplificar la representación de los datos, facilitando su visualización, interpretación y análisis.

Presentaremos dos técnicas comunes de reducción de dimensionalidad:

  1. Análisis de Componentes Principales (PCA):

    • PCA es una técnica lineal que transforma los datos originales en un conjunto de componentes principales no correlacionados. Estos componentes principales capturan la mayor parte de la varianza en los datos, permitiendo la reducción de la dimensionalidad.
  2. T-Distributed Stochastic Neighbor Embedding (t-SNE):

    • t-SNE es una técnica no lineal utilizada principalmente para la visualización de datos en dimensiones reducidas. Se centra en preservar las relaciones locales entre puntos, lo que es útil para la representación visual de la estructura de los datos.

Estas técnicas permiten manejar de manera eficiente conjuntos de datos con un gran número de características y proporcionan una representación más compacta y manejable de la información. La elección de la técnica dependerá de la naturaleza de los datos y los objetivos específicos del análisis.

Análisis de Componentes Principales (PCA)¶

El Análisis de Componentes Principales (PCA) es una técnica de reducción de dimensionalidad que busca transformar un conjunto de datos original en un nuevo conjunto de variables no correlacionadas llamadas componentes principales. El objetivo es retener la mayor cantidad posible de la variabilidad presente en los datos originales. A continuación, se presenta un resumen de los principales aspectos de PCA:

  1. Objetivo:

    • Reducir la dimensionalidad de los datos manteniendo la mayor parte de la información original y la variabilidad.
  2. Proceso:

    • Identificación de las direcciones en las que los datos tienen mayor variabilidad.
    • Construcción de nuevos ejes (componentes principales) que son combinaciones lineales de las variables originales.
  3. Componentes Principales:

    • Son variables no correlacionadas entre sí.
    • Los componentes principales están ordenados en función de la cantidad de varianza que explican, con el primer componente principal capturando la máxima varianza.
  4. Varianza Explicada:

    • PCA proporciona información sobre la cantidad de varianza explicada por cada componente principal.
    • Permite seleccionar un número adecuado de componentes para lograr la reducción de dimensionalidad deseada.
  5. Estandarización de Datos:

    • Es recomendable estandarizar los datos antes de aplicar PCA para asegurar que todas las variables tengan la misma influencia en el análisis.
  6. Usos Comunes:

    • Visualización de datos en dimensiones reducidas.
    • Reducción de la dimensionalidad para facilitar el análisis y la interpretación.
    • Eliminación de la multicolinealidad entre variables.
    • Extracción de características importantes.
  7. Limitaciones:

    • PCA asume linealidad en los datos.
    • Sensible a valores atípicos.
    • Las componentes principales pueden ser difíciles de interpretar directamente en términos de las variables originales.

PCA es una técnica valiosa para reducir la dimensionalidad de conjuntos de datos grandes y complejos, facilitando la interpretación y el análisis mientras se retiene la mayor cantidad posible de información esencial.

Pasos para Análisis de Componentes Principales (PCA)¶

PCA se centra en encontrar las direcciones en las cuales los datos tienen la mayor variabilidad y luego proyectar los datos originales en estas direcciones. A continuación, se presenta una descripción matemática simplificada de los pasos principales de PCA:

1. Estandarización de Datos:

  • Si tenemos un conjunto de datos $X$ con $n$ observaciones y $p$ características, la primera paso es estandarizar los datos restando la media y dividiendo por la desviación estándar para todas las características. Esto se hace para asegurar que todas las variables tengan la misma escala y contribución relativa.

$$ \bar{X} = \frac{1}{n} \sum_{i=1}^{n} X_i $$ $$ X_{\text{estandarizado}} = \frac{X - \bar{X}}{\text{Desviación Estándar}} $$

2. Cálculo de la Matriz de Covarianza:

  • Se calcula la matriz de covarianza $S$ para las características estandarizadas. La covarianza entre dos características $X_i$ y $X_j$ se calcula como:

$$ \text{cov}(X_i, X_j) = \frac{1}{n-1} \sum_{k=1}^{n} (X_{ik} - \bar{X}_i)(X_{jk} - \bar{X}_j) $$

3. Cálculo de Autovectores y Autovalores:

  • Se calculan los autovectores ($v$) y autovalores ($\lambda$) de la matriz de covarianza. Los autovectores representan las direcciones principales y los autovalores indican la cantidad de varianza explicada en cada dirección.

$$ S \mathbf{v} = \lambda \mathbf{v} $$

4. Ordenamiento de Autovectores:

  • Los autovectores se ordenan en función de sus autovalores de mayor a menor. Los primeros autovectores (componentes principales) capturan la mayor varianza en los datos.

5. Proyección de Datos en el Nuevo Espacio:

  • Los datos originales se proyectan en el espacio definido por los autovectores seleccionados para formar los componentes principales.

$$ \text{Nuevo Espacio} = X_{\text{estandarizado}} \times V $$

Donde $V$ es una matriz cuyas columnas son los autovectores seleccionados.

PCA utiliza los autovectores y autovalores, para encontrar las direcciones de máxima variabilidad en los datos. La proyección de datos en estas direcciones reduce la dimensionalidad mientras se retiene la mayor cantidad posible de información.

Autovalores y autovectores¶

En el contexto de álgebra lineal, los autovalores y autovectores son conceptos fundamentales asociados a una matriz. Aquí está la definición de cada uno:

  1. Autovalores (o valores propios):

    • Dada una matriz cuadrada $A$, un escalar $\lambda$ se llama autovalor de $A$ si existe un vector no nulo $v$ tal que al multiplicar $A$ por $v$, obtenemos simplemente el vector escalado por $\lambda$.

    La ecuación que define un autovalor es:

    $$ A \mathbf{v} = \lambda \mathbf{v} $$

    Donde:

    • $A$ es la matriz.
    • $\mathbf{v}$ es el autovector asociado al autovalor $\lambda$.
  2. Autovectores (o vectores propios):

    • Dada una matriz cuadrada $A$, un vector no nulo $\mathbf{v}$ se llama autovector de $A$ si, al multiplicarlo por $A$, obtenemos simplemente el mismo vector escalado por un factor escalar $\lambda$.

    La ecuación que define un autovector es:

    $$ A \mathbf{v} = \lambda \mathbf{v} $$

    Donde:

    • $A$ es la matriz.
    • $\lambda$ es el autovalor asociado al autovector $\mathbf{v}$.

En resumen, al calcular los autovalores y autovectores de una matriz, se busca entender cómo esa matriz afecta a ciertos vectores. Los autovalores proporcionan la información sobre la escala de la transformación, y los autovectores dan la dirección en la que la transformación se realiza simplemente escalando el vector original. En el contexto de PCA, los autovalores representan la cantidad de varianza explicada en cada dirección, y los autovectores representan las direcciones principales (o componentes principales) en las cuales los datos tienen la mayor variabilidad.

Consideremos la siguiente matriz como ejemplo:

$$ A = \begin{bmatrix} 4 & 1 \\ 2 & 3 \end{bmatrix} $$

Paso 1: Cálculo de los Autovalores ($\lambda$): La ecuación característica es $\text{det}(A - \lambda I) = 0$. Para $A$, esto se traduce en:

$$ \text{det}\left(\begin{bmatrix} 4 - \lambda & 1 \\ 2 & 3 - \lambda \end{bmatrix}\right) = (4 - \lambda)(3 - \lambda) - (2 \times 1) = 0 $$

Resolviendo la ecuación cuadrática, obtenemos dos autovalores:

$$ (4 - \lambda)(3 - \lambda) - 2 = \lambda^2 - 7\lambda + 10 = (\lambda - 5)(\lambda - 2) = 0 $$

Los autovalores son $\lambda_1 = 5$ y $\lambda_2 = 2$.

Paso 2: Cálculo de los Autovectores ($\mathbf{v}$): Para cada autovalor $\lambda$, resolvemos el sistema de ecuaciones $(A - \lambda I) \mathbf{v} = \mathbf{0}$.

Para $\lambda_1 = 5$:

$$ (A - 5I)\mathbf{v}_1 = \begin{bmatrix} -1 & 1 \\ 2 & -2 \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} $$

Esto da la ecuación $-x + y = 0$, lo que significa que $y = x$. Un autovector correspondiente es $\mathbf{v}_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix}$.

Para $\lambda_2 = 2$:

$$ (A - 2I)\mathbf{v}_2 = \begin{bmatrix} 2 & 1 \\ 2 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} $$

Esto da la ecuación $2x + y = 0$, lo que significa que $y = -2x$. Un autovector correspondiente es $\mathbf{v}_2 = \begin{bmatrix} 1 \\ -2 \end{bmatrix}$.

Entonces, para la matriz $A$, los autovalores son $\lambda_1 = 5$ y $\lambda_2 = 2$, y los autovectores correspondientes son $\mathbf{v}_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix}$ y $\mathbf{v}_2 = \begin{bmatrix} 1 \\ -2 \end{bmatrix}$.

In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

PCA usando numpy¶

  • Creamos un conjunto bidimensional de datos (aleatorios) con $n=30$ observaciones.

  • Escalamos los datos.

  • Calculamos la matriz de covarianza

  • Calculamos los autovalores y autovectores de la matriz de covarianza.

eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix)
  • Ordenamos los autovalores y autovectores de mayor a menor
sorted_indices = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[sorted_indices]
eigenvectors = eigenvectors[:, sorted_indices]
  • Graficar los resultados.
In [2]:
# Crear un conjunto de datos bidimensional
mean = [0, 0]
n = 30
np.random.seed(42)
c = 0.7
cov = [[1, c], [c, 1]]
data = np.random.multivariate_normal(mean, cov, n)

# Estandarizar los datos restando la media de cada columna y dividiendo por la desviación
scaled_data = (data - np.mean(data, axis=0)) / np.std(data, axis=0)

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=False, figsize=(12,4))

x, y = scaled_data.T
df = pd.DataFrame({'x': x, 'y': y})
s = sns.regplot(data=df, x='x', y='y', fit_reg=True, ci=0,
                   scatter_kws={"s": 20, 'alpha': 0.5, 'color': "seagreen"},
                   line_kws={'color': 'orange'}, ax=ax1
                  )

# Calcular la matriz de covarianza
covariance_matrix = np.cov(scaled_data, rowvar=False)

# Calcular los autovalores y autovectores de la matriz de covarianza
eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix)

# Ordenar los autovalores y autovectores de mayor a menor
sorted_indices = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[sorted_indices]
eigenvectors = eigenvectors[:, sorted_indices]

# Graficar los datos originales escalados y las componentes principales
ax1.quiver(np.mean(scaled_data[:, 0]), np.mean(scaled_data[:, 1]), eigenvectors[0, 0], eigenvectors[1, 0], scale=3, color='red', label='Componente Principal 1')
ax1.quiver(np.mean(scaled_data[:, 0]), np.mean(scaled_data[:, 1]), eigenvectors[0, 1], eigenvectors[1, 1], scale=6, color='blue', label='Componente Principal 2')

ax1.set_xlabel('Variable 1')
ax1.set_ylabel('Variable 2')
ax1.set_title('Datos escalados')
ax1.legend()

# Graficar los datos proyectados
# Proyectar los datos en el nuevo espacio de componentes principales
projected_data = np.dot(scaled_data, eigenvectors)
ax2.scatter(projected_data[:, 0], projected_data[:, 1], label='Datos Proyectados')
ax2.set_xlabel('PC 1')
ax2.set_ylabel('PC 2')
ax2.set_title('Datos Proyectados');
No description has been provided for this image
  • Izquierda: Datos escalados, línea de regresión de mínimos cuadrados (naranja), PC1 (rojo) y PC2 (azul).
  • Derecha: Datos proyectos. Los datos originales se proyectan en el espacio definido por los autovectores seleccionados para formar los componentes principales.

Ejmplo usando sklearn¶

# Escalado estándar de datos
scaler = StandardScaler()
scaler.fit(data[['duration', 'waiting']])
scaled_data = scaler.transform(data[['duration', 'waiting']])

# Ajustar PCA
pca = PCA(n_components=2)
pca.fit(X)
In [3]:
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

data = sns.load_dataset("geyser")

# Escalado estándar de datos
scaler = StandardScaler()
scaler.fit(data[['duration', 'waiting']])
scaled_data = scaler.transform(data[['duration', 'waiting']])
In [4]:
def draw_vector(v0, v1, ax=None):
    ax = ax or plt.gca()
    arrowprops=dict(arrowstyle='->',
                    linewidth=2,
                    shrinkA=0, shrinkB=0)
    ax.annotate('', v1, v0, arrowprops=arrowprops)

# plot data
X = scaled_data

# Add a color (not really necessary)
color = [0 if k == 'short' else 1 for k in data.kind]

# Fit PCA
pca = PCA(n_components=2)
pca.fit(X)

plt.figure(figsize=(12,4))
plt.subplot(1,2,1)
plt.scatter(X[:, 0], X[:, 1], c=color, alpha=0.2)
pc = 1
for length, vector in zip(pca.explained_variance_, pca.components_):
    v = vector * 1 * np.sqrt(length)
    draw_vector(pca.mean_, pca.mean_ + v)
    pc += 1
plt.axis('equal')

plt.subplot(1,2,2)
plt.bar(['PC1', 'PC2'], pca.explained_variance_ratio_)
plt.title('Varianza explicada')
plt.show()
No description has been provided for this image
  • Izquierda: En el gráfico de dispersión se visualiza el dataset escalado con un color de etiqueta dado por la columna data.kind. (No es necesario mostrar, no se ha usado para nuestro análisis de PCA).
  • Derecha: En el gráfico de barras se está visualizando la proporción de varianza explicada por PC1 y PC2.:
    • pca.explained_variance_ratio_: Accede al atributo explained_variance_ratio_ del objeto PCA. Este atributo contiene la proporción de varianza explicada por cada componente principal.
In [5]:
fig, ax = plt.subplots(1, 2, figsize=(18, 6))
fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.2)

# plot data
ax[0].scatter(X[:, 0], X[:, 1], c=color, alpha=0.2)
for length, vector in zip(pca.explained_variance_, pca.components_):
    v = vector * 1 * np.sqrt(length)
    draw_vector(pca.mean_, pca.mean_ + v, ax=ax[0])
ax[0].axis('equal');
ax[0].set(xlabel='duration', ylabel='waiting', title='Original data')

# plot principal components
X_pca = pca.transform(X)
ax[1].scatter(X_pca[:, 0], X_pca[:, 1], c=color, alpha=0.2)
draw_vector([0, 0], [0, 1], ax=ax[1])
draw_vector([0, 0], [2, 0], ax=ax[1])
ax[1].axis('equal')
ax[1].set(xlabel='component 1', ylabel='component 2',
          title='principal components',
          xlim=(-3, 3), ylim=(-1, 1))
plt.show()
No description has been provided for this image

t-distributed Stochastic Neighbor Embedding (t-SNE)¶

t-SNE, que significa "t-distributed Stochastic Neighbor Embedding", es una técnica de reducción de dimensionalidad no lineal utilizada comúnmente en el campo del aprendizaje automático y la visualización de datos. Fue propuesta por Laurens van der Maaten y Geoffrey Hinton en 2008.

La idea central de t-SNE es proyectar datos de alta dimensión en un espacio de baja dimensión (generalmente 2D o 3D) de manera que las similitudes entre puntos en el espacio original se conserven en el espacio proyectado. A diferencia de técnicas de reducción de dimensionalidad lineal como PCA, t-SNE es particularmente efectiva para preservar estructuras no lineales y capturar relaciones no lineales complejas en los datos.

Algunas características clave de t-SNE incluyen:

  1. Preservación de Vecindarios: t-SNE tiende a preservar la proximidad local entre puntos. Puntos que son similares en el espacio original tienden a estar cerca en el espacio proyectado.

  2. Función de Costo: La función de costo de t-SNE se basa en la divergencia de Kullback-Leibler entre las distribuciones de similitud de pares en el espacio original y en el espacio proyectado. Este enfoque se centra en preservar las relaciones de vecindario.

  3. Sensibilidad a la Perplejidad: t-SNE tiene un parámetro llamado "perplejidad" que controla el balance entre la atención a vecinos locales y globales. Ajustar este parámetro puede afectar significativamente los resultados.

  4. No Convexo: La función de costo de t-SNE es no convexa, lo que significa que los resultados pueden depender de la inicialización. En la práctica, suele ser útil ejecutar t-SNE con varias inicializaciones y seleccionar el resultado más consistente.

t-SNE se utiliza a menudo para visualizar conjuntos de datos de alta dimensión en un espacio bidimensional o tridimensional, especialmente cuando se busca explorar y comprender patrones complejos en los datos. Sin embargo, es importante tener en cuenta que t-SNE puede no ser adecuado para la preservación de distancias globales y puede tener limitaciones en la interpretación de la magnitud de las distancias en el espacio proyectado.

El algoritmo t-SNE (t-distributed Stochastic Neighbor Embedding) se basa en la minimización de la divergencia de Kullback-Leibler entre dos distribuciones de probabilidad conjunta, una en el espacio original y otra en el espacio de menor dimensión. Denotaremos las distribuciones de probabilidad conjunta en el espacio original y en el espacio proyectado como (P) y (Q) respectivamente.

El objetivo del algoritmo t-SNE es minimizar la siguiente función de costo:

$$ C = KL(P || Q) = \sum_{i \neq j} p_{ij} \log \frac{p_{ij}}{q_{ij}} $$

Donde:

  • $p_{ij}$ es la probabilidad condicional que mide la similitud entre los puntos $i$ y $j$ en el espacio original.
  • $q_{ij}$ es la probabilidad condicional que mide la similitud entre los puntos $i$ y $j$ en el espacio proyectado.

Las similitudes son calculadas a partir de distribuciones Gaussianas centradas en los puntos $i$ y $j$:

$$ p_{ij} = \frac{\exp\left(-\frac{\|x_i - x_j\|^2}{2\sigma_i^2}\right)}{\sum_{k \neq l} \exp\left(-\frac{\|x_k - x_l\|^2}{2\sigma_k^2}\right)} $$

$$ q_{ij} = \frac{\exp\left(-\frac{\|y_i - y_j\|^2}{2}\right)}{\sum_{k \neq l} \exp\left(-\frac{\|y_k - y_l\|^2}{2}\right)} $$

Donde:

  • $x_i$ y $y_i$ son los puntos correspondientes en los espacios original y proyectado.
  • $\sigma_i$ es la varianza de la distribución condicional $p_{ij}$.
  • $\sum_{k \neq l}$ denota la suma sobre todos los pares distintos de puntos.

El algoritmo utiliza técnicas de descenso de gradiente estocástico para minimizar la función de costo $C$, iterativamente ajustando las posiciones de los puntos en el espacio proyectado. La elección de la perplejidad ($\sigma_i$) influye en la escala de las distribuciones condicionales y, por lo tanto, afecta la estructura del espacio proyectado.

En resumen, t-SNE busca proyectar puntos de un espacio de alta dimensión a un espacio de menor dimensión de manera que las similitudes locales se preserven en la proyección, minimizando la divergencia de Kullback-Leibler entre las distribuciones de probabilidad conjunta en ambos espacios.

Ejemplo usando sklearn¶

Este código crea un conjunto de subgráficos (4 paneles) que muestran visualizaciones de dispersión (scatter plots) utilizando el algoritmo t-SNE con diferentes valores de perplejidad $p \in \{10, 20, 30, 40\}$.

In [6]:
from sklearn.manifold import TSNE

# 'scaled_data' es un conjunto de datos escalado y 'data.kind' contiene las etiquetas de categoría
plt.figure(figsize=(10,10))

# Itera sobre diferentes valores de perplejidad
for index, p in enumerate([10, 20, 30, 40]):

    # Aplica t-SNE con la perplejidad actual
    tsne = TSNE(n_components=2, perplexity=p, random_state=0)
    tsne_results = tsne.fit_transform(scaled_data)

    # Crea un DataFrame con los resultados de t-SNE
    tsne_results = pd.DataFrame(tsne_results, columns=['C1', 'C2'])

    # Agrega las etiquetas de categoría al DataFrame
    tsne_results['kind'] = pd.Categorical(data.kind)

    # Crea un subgráfico en una cuadrícula 2x2
    plt.subplot(2, 2, index+1)

    # Crea un gráfico de dispersión usando Seaborn
    sns.scatterplot(data=tsne_results, x='C1', y='C2', hue="kind", s=40)

    # Establece el título del subgráfico
    plt.title('Perplexity = ' + str(p))

    # Si no es el último subgráfico, elimina la leyenda para evitar superposiciones
    if index != 3:
        plt.legend([],[], frameon=False)

# Muestra la visualización completa
plt.show()
No description has been provided for this image

Perplejidad¶

La perplejidad es un parámetro crítico en el algoritmo t-SNE (t-distributed Stochastic Neighbor Embedding). En t-SNE, la perplejidad controla la cantidad de vecinos cercanos que cada punto considera durante la optimización. Una perplejidad baja significa que cada punto se enfoca en menos vecinos cercanos, mientras que una perplejidad alta significa que cada punto considera más vecinos cercanos.

Interpretación y Consejos para la Perplejidad en t-SNE:

  1. Interpretación de la Perplejidad:

    • En términos prácticos, la perplejidad se asocia a menudo con el número efectivo de vecinos cercanos que se consideran al construir las distribuciones de probabilidad condicional en el espacio original.
    • La perplejidad no tiene una interpretación directa en términos de cantidad de clusters o estructura del espacio de salida, pero influye en la forma en que los puntos se agrupan y distribuyen en el espacio proyectado.
  2. Ajuste de la Perplejidad:

    • No hay un valor "óptimo" de perplejidad que funcione para todos los conjuntos de datos. El valor adecuado depende de la naturaleza de los datos y del patrón que se busca preservar.
    • Experimenta con diferentes valores de perplejidad y observa cómo afectan la estructura y la interpretación visual de los resultados.
  3. Típicos Rangos de Perplejidad:

    • Valores comunes de perplejidad suelen estar en el rango de 5 a 50. Sin embargo, puede ser útil probar valores más altos o más bajos según la complejidad de tus datos.
  4. Prueba Iterativa:

    • Ajusta la perplejidad de manera iterativa. Comienza con valores bajos y aumenta gradualmente, observando cómo cambian los resultados.
  5. Influencia en la Visualización:

    • La elección de la perplejidad puede tener un impacto significativo en la estructura visual de los resultados. Puede afectar la compresión y expansión de grupos de puntos en el espacio proyectado.
  6. Evita Perplejidades Extremas:

    • Evita valores extremadamente bajos (menos de 5) o extremadamente altos (más de 50) a menos que tengas razones específicas para elegirlos.
  7. Enfoque Empírico:

    • La elección de la perplejidad a menudo implica un enfoque empírico y depende del conocimiento del dominio y de la exploración visual de los resultados.

La elección de la perplejidad en t-SNE es más un arte que una ciencia. Experimenta con diferentes valores, observa cómo afectan la estructura de los datos en el espacio proyectado y selecciona el valor que mejor resalta las relaciones de interés en tu conjunto de datos.

Ejercicio¶

Vamos a realizar un ejercicio de reducción de dimnesionalidad para un dataset que contienen histogramas de imágenes tomadas a granos de arroz a diferentes humedades.

El histograma de una imagen es una representación gráfica de la distribución de intensidades de píxeles en esa imagen. En otras palabras, muestra la frecuencia con la que ocurren diferentes niveles de intensidad en la imagen. El eje horizontal del histograma representa los valores de intensidad, mientras que el eje vertical indica la cantidad de píxeles que tienen esa intensidad.

El número de bines histograma de las imágenes de arroz en escala de grises se ha fijado en 44.

In [7]:
data = pd.read_csv('https://raw.githubusercontent.com/marsgr6/r-scripts/master/data/G03_cropG_H_660_660_44_bins.csv')
data.humidity = data.humidity.astype(str)
data.head()
Out[7]:
0 1 2 3 4 5 6 7 8 9 ... 35 36 37 38 39 40 41 42 43 humidity
0 0.0 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.000000 0.00000 ... 0.012158 0.044333 0.354619 0.098181 0.124926 0.136753 0.008118 0.000009 0.000000 10
1 0.0 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.000000 0.00000 ... 0.014039 0.018889 0.141064 0.151785 0.089501 0.119041 0.040481 0.001417 0.000000 10
2 0.0 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.000000 0.00000 ... 0.018064 0.023848 0.141680 0.120306 0.108169 0.121783 0.027558 0.000676 0.000000 10
3 0.0 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.000000 0.00000 ... 0.029847 0.022650 0.035885 0.074686 0.087595 0.107312 0.082734 0.014666 0.000054 10
4 0.0 0.0 0.0 0.000009 0.0 0.000009 0.000027 0.000018 0.000045 0.00009 ... 0.015860 0.043084 0.339896 0.143472 0.115284 0.128973 0.035604 0.001162 0.000000 10

5 rows × 45 columns

Visualizar es entender¶

  • Importante (Visualizar nuestros datos)
In [8]:
plt.figure(figsize=(12,6))
sns.heatmap(data.iloc[:,:-1].T)
t = list(data.humidity.unique())
x = list(data.humidity.value_counts().cumsum())
c = list(data.humidity.value_counts())
plt.vlines(x,
           data.humidity.nunique()*[0],
           data.shape[0]*data.humidity.nunique(), colors="cyan")
plt.hlines([12.5, 42.5], [0, 0], [218, 218], colors="yellow")
[plt.text(v[0]-v[2]//2-6, 2, 'H='+v[1], c='white', fontweight="bold") for v in zip(x, t, c)];
plt.text(5, 12, 'Bin 12', c='white', fontweight="bold");
plt.text(5, 42, 'Bin 42', c='white', fontweight="bold");
plt.show()
No description has been provided for this image

El heatmap anterior muestra los histogramas de (44 bines) para las 219 imágenes presentes en el dataset.

Las barras verticales representan los valores de humedad (clase) para cada imagen.

Fuera de las líneas horizontales, los bines presentan mínima variabilidad (valores constantes).

  • Removeremos dichas variables, columnas$\leq 12$, y columnas$\geq 43$, de acuerdo al gráfico de líneas con barras de error mostrado abajo.
In [9]:
dm = data.melt(id_vars=['humidity'])
dm["bin"] = dm.variable.astype('int')
plt.figure(figsize=(12,4))
sns.lineplot(data=dm, x="variable", y="value",
             hue="humidity", err_style='bars', errorbar=('ci', 68))
plt.show()
No description has been provided for this image
In [10]:
plt.figure(figsize=(10,4))
plt.subplot(1,2,1)
sns.boxenplot(data=data, x='humidity', y='22', hue='humidity')
plt.subplot(1,2,2)
sns.boxenplot(data=data, x='humidity', y='23', hue='humidity')
plt.show()
No description has been provided for this image
In [11]:
plt.figure(figsize=(10,4))
plt.subplot(1,2,1)
sns.kdeplot(data=data, hue='humidity', x='22')
plt.subplot(1,2,2)
sns.kdeplot(data=data, hue='humidity', x='23')
plt.show()
No description has been provided for this image
In [12]:
plt.figure(figsize=(6,4))
sns.scatterplot(data=data, x='22', y='23', hue='humidity')
plt.show()
No description has been provided for this image
In [13]:
from viz import *

all_data = {'img_hist': data}

plot_data(all_data)
interactive(children=(Dropdown(description='ds', options=('img_hist',), value='img_hist'), Dropdown(descriptio…
In [14]:
# standardizing the data
from sklearn.preprocessing import StandardScaler

data_selected = data[data.columns[np.array(range(12,43))]]

scaler = StandardScaler()
data_scaled = scaler.fit_transform(data_selected)
In [15]:
from sklearn.decomposition import PCA

max_comp = 10

pca = PCA(n_components=max_comp).fit(data_scaled)

plt.figure(figsize=(10,4))
plt.subplot(1,2,1)
plt.plot(range(1,max_comp+1), pca.explained_variance_, '-o')
plt.axhline(y=1, color='r', linestyle='--')
plt.ylabel("Eigenvalues")
plt.ylabel("# of Features")
plt.title("PCA Eigenvalues")

plt.subplot(1,2,2)
plt.plot(range(1,max_comp+1), pca.explained_variance_ratio_.cumsum(), '-o')
plt.axhline(y=0.80, color='r', linestyle='--')
plt.ylabel("% Variance Explained")
plt.ylabel("# of Features")
plt.title("PCA Variance Explained")
plt.show();
No description has been provided for this image

Scree plot (Gráfico de Sedimento)¶

  • Algunos elementos clave:
  1. (Panel izquierdo) Scree Plot: El "scree plot" es un gráfico que muestra la proporción de varianza explicada por cada componente principal en orden descendente. Cada punto en el gráfico representa una componente principal, y la altura de la barra o el valor del punto indica cuánta varianza de los datos originales se explica por esa componente.

  2. (Panel derecho) Acumulado de la Proporción de Varianza Explicada: La versión acumulada del "scree plot" muestra la suma acumulativa de la proporción de varianza explicada hasta el componente principal actual. Esto significa que el primer punto en el gráfico acumulado representa la proporción de varianza explicada por el primer componente principal, el segundo punto representa la suma de la varianza explicada por los dos primeros componentes principales, y así sucesivamente.

  3. Interpretación: Un "scree plot" acumulado es útil para tomar decisiones sobre cuántos componentes principales retener en un análisis de PCA. Se busca un punto en el gráfico donde la pendiente se "aplana", lo que sugiere que agregar más componentes principales proporciona rendimientos marginales decrecientes en términos de explicación de varianza. Este punto puede considerarse como un punto de codo en el gráfico.

  4. Objetivo de Retención de Varianza: La elección de cuántos componentes principales retener dependerá del porcentaje acumulado de varianza que se considere suficiente para representar adecuadamente la variabilidad de los datos. Comúnmente, se busca retener un alto porcentaje de varianza, como el 90% o el 95%.

Un "scree plot" acumulado de la proporción de varianza explicada en PCA es una herramienta visual que ayuda a determinar cuántos componentes principales retener para capturar una cantidad significativa de la variabilidad de los datos originales.

  • La elección de retener componentes principales con eigenvalores mayores a 1 en un análisis de componentes principales (PCA) se basa en una regla heurística comúnmente utilizada para determinar cuántos componentes retener. Esta regla se conoce como el "criterio del eigenvalor mayor a 1" (línea roja en el panel izquierdo).

  • La regla del 80% de varianza explicada es otra regla heurística utilizada en el análisis de componentes principales (PCA) para determinar el número de componentes principales a retener. Esta regla sugiere que deberías retener suficientes componentes principales para explicar al menos el 80% de la varianza total en los datos originales (línea roja en el panel derecho).

Esta regla es una guía flexible y puede ajustarse según los requisitos específicos del problema. En algunos casos, podría optarse por una regla del 90% o 95% si se busca conservar más varianza. También es importante considerar la interpretabilidad de los resultados y cómo afecta la elección del número de componentes principales.

In [16]:
pca = PCA(n_components=2)

principalComponents = pca.fit_transform(data_scaled)

pc_transformation = pd.DataFrame(data = principalComponents,
                           columns = ['PC1', 'PC2'])

pc_transformation['humidity'] = pd.Categorical(data.humidity)

sns.scatterplot(data=pc_transformation, x="PC1", y="PC2", hue="humidity")
plt.show()
No description has been provided for this image
  • Gráfico de dispersión donde cada punto representa una observación en el espacio bidimensional definido por las componentes principales PC1 y PC2.

    • Los puntos estarán coloreados de acuerdo con los valores de la variable "humidity". Esto es útil para visualizar patrones o agrupaciones en los datos en función de las componentes principales y cómo se relacionan con la variable de humedad.
  • A continuación el gráfico de dispersión en 3 dimensiones, agregando una componente adicional (PC3).

In [17]:
pca = PCA(n_components=3)

principalComponents = pca.fit_transform(data_scaled)

pc_transformation = pd.DataFrame(data = principalComponents,
                           columns = ['PC1', 'PC2', 'PC3'])

pc_transformation['humidity'] = pd.Categorical(data.humidity)

pc_transformation['size'] = 10
In [18]:
import plotly.express as px

fig = px.scatter_3d(pc_transformation, x='PC1', y='PC2', z='PC3',
              color='humidity', size='size', size_max=10)
fig.show()
/srv/conda/envs/notebook/lib/python3.10/site-packages/plotly/express/_core.py:2044: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
  grouped = df.groupby(required_grouper, sort=False)  # skip one_group groupers

Ejercicio t-SNE¶

  • Aplicaremos t-SNE al dataset de histogramas de imágenes de arroz y humedad.
In [19]:
from sklearn.manifold import TSNE

plt.figure(figsize=(10,10))
for index, p in enumerate([10, 20, 30, 40]):

    tsne = TSNE(n_components = 2, perplexity = p, random_state=0)
    tsne_results = tsne.fit_transform(data_scaled)

    tsne_results=pd.DataFrame(tsne_results, columns=['C1', 'C2'])

    tsne_results['humidity'] = pd.Categorical(data.humidity)

    plt.subplot(2,2,index+1)
    sns.scatterplot(data=tsne_results, x='C1', y='C2',
                    hue="humidity", s=40)
    plt.title('Perplexity = '+ str(p))
    if index != 3: plt.legend([],[], frameon=False)
plt.show()
No description has been provided for this image

Anexo: Graficos PCA¶

Requisitos

!pip install pca

El paquete pca anterior facilita la visualización de los resultados de PCA de forma gráfica.

# Plot the explained variance
fig, ax = model.plot()
plt.show()

# Scatter the first two PCs
fig, ax = model.scatter()
plt.show()

# Create a biplot
fig, ax = model.biplot(n_feat=4)
plt.show()
  • Vea: https://pypi.org/project/pca/
In [20]:
from pca import pca

model = pca(n_components=2)

# Fit and transform
results = model.fit_transform(X=pd.DataFrame(data_scaled, columns=data_selected.columns),
                              row_labels=data.humidity)

# Create a biplot
fig, ax = model.biplot(n_feat=4)
plt.show()
[scatterd] >INFO> Create scatterplot
[pca] >Extracting column labels from dataframe.
[pca] >The PCA reduction is performed on the [31] columns of the input dataframe.
[pca] >Fit using PCA.
[pca] >Compute loadings and PCs.
[pca] >Compute explained variance.
[pca] >Outlier detection using Hotelling T2 test with alpha=[0.05] and n_components=[2]
[pca] >Multiple test correction applied for Hotelling T2 test: [fdr_bh]
[pca] >Outlier detection using SPE/DmodX with n_std=[3]
[pca] >Plot PC1 vs PC2 with loadings.
No description has been provided for this image

Biplot¶

Un biplot en el contexto de Análisis de Componentes Principales (PCA) es una representación gráfica que combina la información de las proyecciones de los puntos de datos y las direcciones de las variables originales en el espacio de los componentes principales. Aquí hay una guía básica sobre cómo interpretar un biplot en PCA:

  1. Puntos de Datos:

    • Cada punto en el biplot representa una observación o un caso en el conjunto de datos original. La posición de un punto en el biplot está determinada por sus coordenadas en el espacio de los componentes principales.
  2. Direcciones de las Variables Originales:

    • Las flechas en el biplot representan las direcciones de las variables originales en el espacio de los componentes principales. La longitud y la dirección de cada flecha indican la contribución y la dirección de máxima variabilidad de cada variable en los componentes principales.
  • Variables con flechas largas: Contribuyen significativamente a la variabilidad en los datos y son consideradas como importantes en términos de su impacto en los componentes principales.

  • Variables con flechas cortas: Tienen una contribución menor a la variabilidad y pueden considerarse como menos importantes en el contexto de PCA.

  • Esta interpretación es valiosa al seleccionar las características más relevantes o al intentar comprender qué variables están impulsando la estructura de los datos en el espacio de componentes principales.

  1. Proximidad entre Puntos y Flechas:

    • La proximidad de un punto a una flecha indica la relación entre la observación y la variable correspondiente. Si un punto está cerca de una flecha, significa que esa observación tiene un alto valor en esa variable. Si un punto y una flecha tienen una orientación similar, sugiere que hay una relación positiva entre la variable y la observación.
  2. Correlación entre Variables:

    • La correlación entre dos variables puede ser inferida por el ángulo entre las flechas correspondientes en el biplot. Un ángulo pequeño sugiere una correlación positiva, mientras que un ángulo cercano a 180 grados sugiere una correlación negativa.
  3. Concentración de Varianza:

    • La concentración de puntos en ciertas direcciones del biplot indica la cantidad de varianza capturada por esos componentes principales. Las direcciones con más puntos indican las direcciones de mayor variabilidad en los datos.
  4. Identificación de Grupos:

    • Si hay grupos o patrones en los datos, es posible que los puntos de esos grupos estén cerca unos de otros y tengan orientaciones similares en relación con las flechas de las variables.

El biplot en PCA proporciona una representación visual intuitiva de las relaciones entre las observaciones y las variables en el espacio de los componentes principales. Es una herramienta valiosa para interpretar la estructura de los datos y para identificar patrones, correlaciones y contribuciones relativas de las variables a la variabilidad en los datos.

Variables importantes¶

  • El uso de los bines 22 y 23 en el análisis exploratorio, no fue una casualidad.
  • Se eligieron estas variables de acuerdo a su importancia según Random Forest.
  • Son estas variables importante las que separan mejor sus clases en un modelo de clasificación o explican mejor la varianza de sus datos en un problema de regresión.
  • Estas son las variables que quiere incluir en su análisis exploratorio.

Random Forest para obtener la Importancia de Características¶

Random Forest (Bosque Aleatorio) es un algoritmo de aprendizaje automático que pertenece a la categoría de ensambles, específicamente, a los ensambles de árboles de decisión. La idea central detrás de Random Forest es construir múltiples árboles de decisión durante el entrenamiento y combinar sus predicciones para obtener un resultado más robusto y preciso.

Aquí hay una descripción básica de cómo funciona Random Forest:

  1. Construcción de Múltiples Árboles:

    • Se crean varios árboles de decisión durante el entrenamiento, cada uno basado en una muestra aleatoria del conjunto de datos (bootstrap) y utilizando un subconjunto aleatorio de las características para dividir los nodos.
  2. Votación por Mayoría o Promedio:

    • Para realizar predicciones, cada árbol en el bosque emite su propia predicción. En el caso de clasificación, se realiza una votación por mayoría para determinar la clase final, y en el caso de regresión, se realiza un promedio de las predicciones de los árboles.
  3. Bootstrap y Muestreo de Características:

    • El uso de bootstrap (muestreo con reemplazo) y la selección aleatoria de características ayuda a introducir variabilidad en cada árbol, lo que mejora la generalización y la robustez del modelo.
  4. Reducción de la Correlación entre Árboles:

    • Dado que cada árbol se construye en una muestra diferente y utiliza un conjunto diferente de características para tomar decisiones, los árboles en el bosque son menos propensos a estar altamente correlacionados entre sí.
  5. Manejo de Datos No Balanceados:

    • Random Forest tiende a manejar bien conjuntos de datos no balanceados y es menos propenso al sobreajuste en comparación con un solo árbol de decisión.
  6. Importancia de Características:

    • Random Forest proporciona una medida de la importancia de cada característica en el proceso de toma de decisiones, lo que puede ser útil para la interpretación del modelo.

Random Forest se utiliza comúnmente en tareas de clasificación y regresión y ha demostrado ser efectivo en una variedad de dominios. Su capacidad para manejar conjuntos de datos grandes y complejos, así como su resistencia al sobreajuste, lo convierten en una opción popular en la práctica del aprendizaje automático.

In [21]:
from sklearn.ensemble import RandomForestClassifier

X = data_selected
y = data.humidity

rf = RandomForestClassifier(n_estimators=100, random_state=123)
# cambiar valores de acuerdo al numero de columnas en el dataset
rf.fit(X, y)
Out[21]:
RandomForestClassifier(random_state=123)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(random_state=123)
In [22]:
sns.reset_defaults()
sorted_idx = rf.feature_importances_.argsort()
plt.barh(X.columns[sorted_idx][:], rf.feature_importances_[sorted_idx][:])
plt.xlabel("Random Forest Feature Importance")
plt.show()
No description has been provided for this image

Fuentes y recursos¶

  • https://towardsdatascience.com/t-sne-clearly-explained-d84c537f53a
  • https://shankarmsy.github.io/posts/pca-vs-lr.html
  • https://jakevdp.github.io/PythonDataScienceHandbook/index.html
  • https://jakevdp.github.io/PythonDataScienceHandbook/05.09-principal-component-analysis.html